package org.jetlinks.community.mstn.web;

import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.hswebframework.ezorm.core.param.Term;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.authorization.Authentication;
import org.hswebframework.web.authorization.Dimension;
import org.hswebframework.web.authorization.annotation.Authorize;
import org.hswebframework.web.authorization.annotation.Resource;
import org.hswebframework.web.authorization.annotation.ResourceAction;
import org.hswebframework.web.authorization.exception.UnAuthorizedException;
import org.hswebframework.web.crud.service.ReactiveCrudService;
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
import org.hswebframework.web.exception.BusinessException;
import org.jetlinks.community.device.entity.AssetsEntity;
import org.jetlinks.community.device.entity.DeviceInstanceEntity;
import org.jetlinks.community.device.entity.request.AssetsBindRequest;
import org.jetlinks.community.device.service.AssetsService;
import org.jetlinks.community.device.service.LocalDeviceInstanceService;
import org.jetlinks.community.mstn.entity.AssetPermission;
import org.jetlinks.community.mstn.entity.BindingsAssetPermission;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 资产管理
 *
 */
@RestController
@RequestMapping("/assets")
@Authorize
@Resource(id = "assets", name = "资产管理", group = "mstn")
@Tag(name = "资产管理")
@AllArgsConstructor
public class AssetsController implements ReactiveServiceCrudController<AssetsEntity, String> {

    private final AssetsService assetsService;

    private final LocalDeviceInstanceService deviceInstanceService;

    @Override
    public ReactiveCrudService<AssetsEntity, String> getService() {
        return assetsService;
    }


    @GetMapping("/bindings/product/permissions")
    @Operation(summary = "获取权限数据字典")
    public Flux<AssetPermission> productPermissions(){
        AssetPermission read = new AssetPermission();
        read.setId("read");
        read.setName("查看");
        AssetPermission save = new AssetPermission();
        save.setId("save");
        save.setName("编辑");
        AssetPermission delete = new AssetPermission();
        delete.setId("delete");
        delete.setName("删除");
        AssetPermission share = new AssetPermission();
        share.setId("share");
        share.setName("共享");
        return Flux.fromIterable(Arrays.asList(read, save, delete, share));
    }

    @GetMapping("/bindings/device/permissions")
    @Operation(summary = "获取绑定设备权限")
    public Flux<AssetPermission> devicePermissions(){
        AssetPermission read = new AssetPermission();
        read.setId("read");
        read.setName("查看");
        AssetPermission save = new AssetPermission();
        save.setId("save");
        save.setName("编辑");
        AssetPermission delete = new AssetPermission();
        delete.setId("delete");
        delete.setName("删除");
        AssetPermission share = new AssetPermission();
        share.setId("share");
        share.setName("共享");
        return Flux.fromIterable(Arrays.asList(read, save, delete, share));
    }


    @PostMapping("/bind/{assets}")
    @Operation(summary = "绑定资产")
    @ResourceAction(id = "bind-assets", name = "绑定资产")
    public Mono<Boolean> bindAssets(@PathVariable String assets,@RequestBody Flux<AssetsBindRequest> deviceFlux){
        return assetsService.bindAssets(assets, deviceFlux).thenReturn(true);
    }

    @PostMapping("/unbind/{assets}")
    @Operation(summary = "解绑资产")
    @ResourceAction(id = "unbind-assets", name = "解绑资产")
    public Mono<Boolean> unbindAssets(@PathVariable String assets,@RequestBody Flux<AssetsBindRequest> deviceFlux){
        return assetsService.unbindAssets(assets,deviceFlux).thenReturn(true);
    }

    @PostMapping("/search/device")
    @Operation(summary = "查询设备列表" ,description = "暂时不用了")
    public Mono<PagerResult<DeviceInstanceEntity>> search(@RequestBody QueryParamEntity query) {
        return Authentication
            .currentReactive()
            .switchIfEmpty(Mono.error(UnAuthorizedException::new))
            .flatMap(authentication-> {
                if ("admin".equals(authentication.getUser().getUsername())){
                    return deviceInstanceService.queryPager(query);
                } else {
                    //拥有的机构，只能查询自己所在机构的机构数据
                    Map<String, String> orgMapping = authentication
                        .getDimensions("org")
                        .stream()
                        .collect(Collectors.toMap(Dimension::getId, Dimension::getName, (_1, _2) -> _1));
                    //不存在机构
                    if (orgMapping.size() == 0) {
                        return Mono.just(new PagerResult<>());
                    }

                    List<Term> terms = query.getTerms();
                    for (Term term : terms) {

                        Map<String , Object> value ;
                        if (term.getValue() instanceof String) {
                            value = JSON.parseObject((String) term.getValue());
                        } else if(term.getValue() instanceof Map) {
                            value = (Map<String, Object>) term.getValue();
                        } else {
                            return Mono.error(new BusinessException("数据类型不支持"));
                        }

                        List<Map<String ,String>> targets = (List<Map<String, String>>) value.get("targets");
                        targets = targets.stream().filter(target -> orgMapping.containsKey(target.get("id"))).collect(Collectors.toList());
                        value.put("targets",targets);
                        //过滤后没有机构
                        if (targets.size() == 0) {
                            return Mono.just(new PagerResult<>());
                        }
                    }
                    query.setTerms(terms);
                    return deviceInstanceService.queryPager(query);
                }
            });
    }


    @PostMapping("/bindings/device")
    @Operation(summary = "查询设备列表")
    public Mono<List<BindingsAssetPermission>> bindingsDevice(@RequestBody List<String> deivceIds) {
        List<BindingsAssetPermission> result = new ArrayList<>();
        for (String productId: deivceIds){
            List<AssetPermission> list = new ArrayList<>();
            AssetPermission read = new AssetPermission();
            read.setId("read");
            read.setName("查看");
            AssetPermission save = new AssetPermission();
            save.setId("save");
            save.setName("编辑");
            AssetPermission delete = new AssetPermission();
            delete.setId("delete");
            delete.setName("删除");
            AssetPermission share = new AssetPermission();
            share.setId("share");
            share.setName("共享");
            list.add(read);
            list.add(save);
            list.add(delete);
            list.add(share);

            BindingsAssetPermission model = new BindingsAssetPermission();
            model.setAssetId(productId);
            model.setPermissionInfoList(list);
            result.add(model);
        }

        return Mono.just(result);
    }

    @PostMapping("/bindings/product")
    @Operation(summary = "查询产品列表")
    public Mono<List<BindingsAssetPermission>> bindingsProduct(@RequestBody List<String> productIds) {
        List<BindingsAssetPermission> result = new ArrayList<>();
        for (String productId: productIds){
            List<AssetPermission> list = new ArrayList<>();
            AssetPermission read = new AssetPermission();
            read.setId("read");
            read.setName("查看");
            AssetPermission save = new AssetPermission();
            save.setId("save");
            save.setName("编辑");
            AssetPermission delete = new AssetPermission();
            delete.setId("delete");
            delete.setName("删除");
            AssetPermission share = new AssetPermission();
            share.setId("share");
            share.setName("共享");
            list.add(read);
            list.add(save);
            list.add(delete);
            list.add(share);

            BindingsAssetPermission model = new BindingsAssetPermission();
            model.setAssetId(productId);
            model.setPermissionInfoList(list);
            result.add(model);
        }

        return Mono.just(result);
    }
    @PostMapping("/bindings/{assets}/{type}/{typeId}/_query")
    @Authorize(ignore = true)
    @Operation(summary = "查询设备列表权限")
    public Mono<List<BindingsAssetPermission>> search(@PathVariable String assets,  @PathVariable String type, @PathVariable String typeId, @RequestBody List<String> deivceIds){

        List<BindingsAssetPermission> result = new ArrayList<>();
        for (String productId: deivceIds){
            List<AssetPermission> list = new ArrayList<>();
            AssetPermission read = new AssetPermission();
            read.setId("read");
            read.setName("查看");
            AssetPermission save = new AssetPermission();
            save.setId("save");
            save.setName("编辑");
            AssetPermission delete = new AssetPermission();
            delete.setId("delete");
            delete.setName("删除");
            AssetPermission share = new AssetPermission();
            share.setId("share");
            share.setName("共享");
            list.add(read);
            list.add(save);
            list.add(delete);
            list.add(share);

            BindingsAssetPermission model = new BindingsAssetPermission();
            model.setAssetId(productId);
            model.setPermissionInfoList(list);
            model.setGrantedPermissions(list);

            result.add(model);
        }

        return Mono.just(result);

    }



}
